Skip to content

use MemoryPool<byte> sources for request/response buffering#3103

Open
mgravell wants to merge 5 commits into
v3from
marc/cyclebufferpool
Open

use MemoryPool<byte> sources for request/response buffering#3103
mgravell wants to merge 5 commits into
v3from
marc/cyclebufferpool

Conversation

@mgravell

@mgravell mgravell commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator
  • (SE.Redis) add MemoryPool<byte> config options (runtime API only, no parse support)
  • (RESPite) add CycleBufferPool<T> : MemoryPool<T> with support for allocating with reference to an existing ReadOnlySequence<T>
  • (RESPite) add MemoryPoolExtensions with utility methods to rent via ReadOnlySequence<T>, testing for CycleBufferPool<T> else applying default (doubling) logic
  • (SE.Redis) use from Lease<byte> response handler
  • (resp-benchmark) support -d in the benchmark

In addition to isolation, allowing a growth strategy improves performance when dealing with large payloads (-d 500000):

V2

dotnet run -p:TargetVer=2 -f net10.0 -c Release -- -q -c 50 -P 2 +m --queue
  -n 5000 -q -l -t GET -d 500000
### classic SE.Redis 2.13.17.28173 ###
SET:    3,564 requests per second
GET:    3,058 requests per second
SET:    1,902 requests per second
GET:    2,474 requests per second
SET:    3,136 requests per second
GET:    2,950 requests per second
SET:    4,485 requests per second
GET:    4,074 requests per second
SET:    4,831 requests per second
GET:    4,014 requests per second
SET:    5,361 requests per second
GET:    4,630 requests per second
SET:    4,966 requests per second
GET:    4,308 requests per second

V3 before this change

dotnet run -p:TargetVer=3 -f net10.0 -c Release -- -q -c 50 -P 2 +m --queue
  -n 5000 -q -l -t GET -d 500000
### classic SE.Redis 3.0.0.11234 ###
SET:    1,820 requests per second
GET:    4,454 requests per second
SET:    1,592 requests per second
GET:    2,851 requests per second
SET:    1,460 requests per second
GET:    5,032 requests per second
SET:    1,917 requests per second
GET:    4,804 requests per second
SET:    1,869 requests per second
GET:    4,814 requests per second
SET:    1,850 requests per second
GET:    4,866 requests per second

V3 after this change

dotnet run -p:TargetVer=3 -f net10.0 -c Release -- -q -c 50 -P 2 +m --queue
  -n 5000 -q -l -t GET -d 500000
### classic SE.Redis 3.0.0.11234 ###
SET:    5,974 requests per second
GET:    7,224 requests per second
SET:    5,725 requests per second
GET:    7,162 requests per second
SET:    6,617 requests per second
GET:    8,159 requests per second
SET:    5,781 requests per second
GET:    8,213 requests per second
SET:    6,736 requests per second
GET:    8,233 requests per second
SET:    6,962 requests per second
GET:    6,915 requests per second
SET:    6,368 requests per second
GET:    8,142 requests per second

…<byte> with the growth logic

- support `-d` in the benchmark
- add [SkipLocalsInit] to RESPite
@pairbit

pairbit commented Jun 17, 2026

Copy link
Copy Markdown

The idea is sound, but I'm looking at a different approach here - to allow more flexibility without hard coding specific things like the power factor into the API; thoughts? #3103

This is definitely correct. This will completely solve the memory control issue for requests, but not for responses.

I propose to add ResponseArrayPool for oversized payload.
I would also like to see it used in the Lease class.

var arrayPool = BridgeCouldBeNull?.Multiplexer.RawConfig.ResponseArrayPool ?? ArrayPool<byte>.Shared;

byte[]? oversized = arrayPool.Rent(len);
payload.CopyTo(oversized);
OnResponseFrame(prefix, new(oversized, 0, len), ref oversized);

// the lease could have been claimed by the activation code (to prevent another memcpy); otherwise, free
if (oversized is not null)
{
    arrayPool.Return(oversized);
}

#3104

@mgravell mgravell changed the base branch from v3 to main June 22, 2026 11:19
@mgravell mgravell changed the base branch from main to v3 June 22, 2026 11:20
pairbit and others added 2 commits June 22, 2026 15:52
* add ResponseArrayPool

* Lease

* IMemoryOwner<byte>?

---------

Co-authored-by: ITikhonov <ITikhonov@lanit.ru>
@mgravell mgravell changed the title introduce CycleBufferPool use MemoryPool<byte> sources for request/response buffering Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants